/***************
*相关论文：https://wenku.baidu.com/view/e087065f804d2b160b4ec0b5.html
×
*
****************/

#include <algorithm>
#include <stdio.h>

#define N 10010

using namespace std;

//使用链式前向星表示点的邻接边
//注意节点序号从1开始
struct NEdge  { //nabhor edge
    int to;  //终点
    int pre; //上一个邻接边索引
    int l; //边长
} el[N*2];
int ecnt = 0; //边数
int head[N]; //节点的最后一个邻接点表
int nwcdis[N]; //节点到重心的距离
int ncnt; //nwcid有效元素个数
int maxcn[N]; //最大子树的节点数
int tnodes[N]; //树的节点数
bool vis[N]; //是否以作为重心访问过
int n /*节点数*/, k /*距离阀值*/;
int ans = 0; //最终结果

//递归(向子树）计算初始树的节点数和最大下行子树的节点数
//u: 树的根节点
//p: 父节点(防止向上查找)，初始树根的根节点设为0
void dfs_size(int u, int p) {
    tnodes[u] = 1;
    maxcn[u] = 0; 
    for(int i=head[u]; ~i; i=el[i].pre) {
        int v = el[i].to;
        if(v == p || vis[v]) continue; //跳过父节点
        dfs_size(v, u);
        tnodes[u] += tnodes[v];
        if(tnodes[v] > maxcn[u]) maxcn[u] = tnodes[v];
    }

}

int mcn = N; //r中当前预备重心的最大子树的节点数
int root = 0; //重心
//计算树r的重心
//r: 树根节点
//u: 树中待判断的点(计算最大子树节点数)
//p: u的父节点，防止向上回溯
//每次顶层调用dfs_root时必须线最大化mcn
void dfs_root(int r, int u, int p) {
    int ucn = tnodes[r]-tnodes[u]; //u相对r的向上子树的节点数
    if(maxcn[u] < ucn) maxcn[u] = ucn;
    if(maxcn[u] < mcn) { 
        mcn = maxcn[u];
        root = u;
    }
    for(int i=head[u]; ~i; i=el[i].pre) {
        int v = el[i].to;
        if(v == p || vis[v]) continue; //跳过父节点
        dfs_root(r, v, u); 
    }
}

//计算过重心满足条件的路径数(同分支的也计算)
int calc(int s) {
    sort(nwcdis+s, nwcdis+ncnt);
    int res = 0;
    for(int i=s, j=ncnt-1; i<j; ) {
        if(nwcdis[i]+nwcdis[j]<=k) {
            res += j-i;
            i++;
        }else {
            j--;
        }
    }
    return res;
} 

//计算子树u中各节点到特定重心的距离(dfs遍历各节点)
//u: 子树的树根(开始为重心)
//p: u的父节点
//d: 节点u到重心的距离
//resize nwcdis to 0 before calling this
//time: O(n*log(n)) ?
void dfs_dis(int u, int p, int d) {
    nwcdis[ncnt++] = d;
    int os; //old size
    for(int i=head[u]; ~i; i=el[i].pre) {
        int v = el[i].to;
        if(v == p || vis[v]) continue;
        if(!p) os = ncnt;
        dfs_dis(v, u, d+el[i].l);
        if(!p) ans -= calc(os); //去掉重心子树中非法的计数
    }
}


//计算树中满足条件的路径树，注意子树的范围通过重心划分
//r: 树根
void dfs(int r) { 
    dfs_size(r, 0);
    mcn = N;
    dfs_root(r, r, 0);
    ncnt = 0;
    dfs_dis(root, 0, 0); //注意这里将树的根改为重心
    ans += calc(0);
    vis[root] = true; //标记root被作为重心处理, 在dfs递归之前
    //以重心为根划分子树
    for(int i=head[root]; ~i; i=el[i].pre) {
        int v=el[i].to;
        if(vis[v]) continue;
        dfs(v);
    }
}

void init(void) {
    for(int i=1; i<=n; i++) {
        head[i] = -1;
        vis[i] = false;
    }
    ans = 0; ecnt = 0;
}

int main(void) {
    int u, v, l;
    while(true) {
        scanf("%d%d", &n, &k);
        if(!n) break;
        init();
        for(int i=1; i<n; i++) {
            scanf("%d%d%d", &u, &v, &l);
            el[ecnt].to = v;
            el[ecnt].pre = head[u];
            el[ecnt].l = l;
            head[u] = ecnt++;
            el[ecnt].to = u;
            el[ecnt].pre = head[v];
            el[ecnt].l = l;
            head[v] = ecnt++;
        }
        dfs(1);
        printf("%d\n", ans);
    } 
    return 0;
}
